//go:build windows

package pcboard

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/StackExchange/wmi"
	"github.com/urfave/cli/v2"
	"os"
)

var (
	BuildTime string
	Version   = "1.0.0"
)

func Do() {
	app := cli.NewApp()

	app.Name = "board"
	app.Version = fmt.Sprintf("%s build:%s", Version, BuildTime)
	app.Usage = "通过 wmi 获取基板和bios信息,返回值为 BaseBoard 对象"
	app.Description = "基于wmi获取主板和bios信息"
	app.Flags = []cli.Flag{
		&cli.StringFlag{
			Name:        "type",
			Aliases:     []string{"t"},
			Required:    true,
			DefaultText: "base",
			Usage:       "获取主板信息，可选参数：board、bios、base,",
		},
		&cli.BoolFlag{
			Name:    "serial",
			Aliases: []string{"s"},
			Usage:   "获取序列号信息",
		},
	}
	app.Action = func(ctx *cli.Context) error {
		var (
			typeStr    string
			isSerial   bool
			baseInfo   BaseBoard
			baseSerial BaseSerial
			boardLi    []Board
			biosLi     []Bios

			err error
			bs  []byte
		)
		typeStr = ctx.String("type")
		isSerial = ctx.IsSet("serial")
		w := bufio.NewWriter(os.Stdout)
		switch typeStr {
		case "base":
			if baseInfo, err = baseboardInfo(); err != nil {
				return err
			}
			if isSerial {
				baseSerial = BaseSerial{
					BoardSerial: baseInfo.BoardSerialNumber,
					BioSerial:   baseInfo.BiosSerialNumber,
				}
				if bs, err = json.Marshal(baseSerial); err != nil {
					return err
				}
				w.WriteString(string(bs) + "\n")
			} else {
				if bs, err = json.Marshal(baseInfo); err != nil {
					return err
				}
				w.WriteString(string(bs) + "\n")
			}
		case "board":
			if boardLi, err = board(); err != nil {
				return err
			}
			if isSerial {
				if len(boardLi) > 0 {
					w.WriteString(boardLi[0].SerialNumber + "\n")
				} else {
					w.WriteString("unknown" + "\n")
				}
			} else {
				if bs, err = json.Marshal(boardLi); err != nil {
					return err
				}
				w.WriteString(string(bs) + "\n")
			}
		case "bios":
			if biosLi, err = bios(); err != nil {
				return err
			}
			if isSerial {
				if len(biosLi) > 0 {
					w.WriteString(biosLi[0].SerialNumber + "\n")
				} else {
					w.WriteString("unknown" + "\n")
				}
			} else {
				if bs, err = json.Marshal(biosLi); err != nil {
					return err
				}
				w.WriteString(string(bs) + "\n")
			}
		default:
			return cli.Exit("type 参数错误", 1)
		}
		w.Flush()
		return nil
	}
	if err := app.Run(os.Args); err != nil {
		fmt.Printf("命令行调用错误：%s ，请查看帮助文档", err.Error())
	}
}

// Board for  Win32_BaseBoard
type Board struct {
	Description          string // eg:基板 , 对象的描述（底板）
	HostingBoard         bool   // eg:TRUE,如果为TRUE，该卡是一个主板，或在一个机箱中的基板。
	HotSwappable         bool   // eg:FALSE,如果为TRUE，就是支持热插拔（判断是否支持热插拔）
	Manufacturer         string // eg:HASEE Computer,表示制造商的名称
	Model                string // eg:null ,物理元素的名称是已知。
	Name                 string // eg:基板 ,对象的名称标签
	OtherIdentifyingInfo string // eg:null ,捕获附加数据，超出资产标签的信息，可以用来标识物理元件
	Product              string // eg:H310CM, 产品的型号
	SerialNumber         string // eg:00000000 ，经过测试大品牌机器这个值都是有唯一值的，我的是杂牌电脑 .制造商分配的用于识别所述物理元件数目。
	Tag                  string // eg:Base Board,系统的基板唯一标识
	Version              string // eg:F1.0G,物理元素的版本
}

// Bios for Win32_BIOS
type Bios struct {
	SerialNumber string // eg:EJVPM21124000449 , 序列号
	Manufacturer string // eg:HUAWEI , 制造商
}

// BaseBoard 主板概述信息
type BaseBoard struct {
	BoardSerialNumber string `json:"boardSerialNumber,omitempty"`
	BoardManufacturer string `json:"boardManufacturer,omitempty"`
	BoardProduct      string `json:"boardProduct,omitempty"`
	BiosSerialNumber  string `json:"biosSerialNumber,omitempty"`
	BiosManufacturer  string `json:"biosManufacturer,omitempty"`
}
type BaseSerial struct {
	BoardSerial string `json:"boardSerial,omitempty"`
	BioSerial   string `json:"bioSerial,omitempty"`
}

// 获取基础信息
func baseboardInfo() (b BaseBoard, err error) {
	var board []Board
	var bios []Bios
	err = wmi.Query("SELECT * FROM Win32_BaseBoard", &board)
	if err != nil {
		return b, err
	}
	err = wmi.Query("SELECT * FROM Win32_BIOS", &bios)
	if err != nil {
		return b, err
	}
	for _, v := range board {
		if v.HostingBoard {
			b.BoardProduct = v.Product
			b.BoardSerialNumber = v.SerialNumber
			b.BoardManufacturer = v.Manufacturer
		}
	}
	if len(bios) > 0 {
		b.BiosManufacturer = bios[0].Manufacturer
		b.BiosSerialNumber = bios[0].SerialNumber
	}
	return b, nil
}

// 获取board信息
func board() (li []Board, err error) {
	err = wmi.Query("SELECT * FROM Win32_BaseBoard", &li)
	return
}

// 获取bios信息
func bios() (li []Bios, err error) {
	err = wmi.Query("SELECT * FROM Win32_BIOS", &li)
	return
}
